/*!
 * DL.js v0.0.1
 * (c) 2020-2021 大方前端
 */
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    typeof define === 'function' && define.amd ? define(factory) :
      (global = global || self, global.DL = factory());
}(this, function () {
  // 'use strict';
  /**
   * 构造函数
   * @copyright 前端 2021
   * @param {string} id 容器id
   * @param {string} options L.map的原始配置项
   * @constructor
   * @classdesc 是对leaflet的二次封装.
   */
  function DL (id, options) {
    this.id = id
    this.options = options || {}
    this.map = null
    this.init()
  }

//初始化地图
  DL.prototype.init = function () {
    this.map = L.map(this.id, this.options)
    if (this.options && this.options.layerNames) {
      if (this.options.layerNames.length > 1) {
        var baseLayers = {}
        var layerNames = this.options.layerNames
        for (var i = 0; i < layerNames.length; i++) {
          baseLayers[layerNames[i]] = this.options.layers[i]
        }
        L.control.layers(baseLayers, null).addTo(this.map)
      }
    }
  }
  /**
   * 地图上加点
   * @param {object} obj 对marker点,圆原始的配置
   * @return {object} 返回marker和circle的对象
   */
  DL.prototype.addPoint = function (obj) {
    var pointObj = {
      marker: null,
      circle: null
    }
    if (obj.marker) {
      var oriOptions = obj.marker.oriOptions || {}
      pointObj.marker = L.marker(obj.marker.latLng, oriOptions).addTo(this.map) //.marker添加标注点
      if (obj.marker.bindPopup) {
        pointObj.marker.bindPopup(obj.marker.bindPopup.content || '')
      }
      if (obj.marker.openPopup) {
        pointObj.marker.openPopup()
      }
    }
    if (obj.circle) {
      var oriOptions = obj.circle.oriOptions || {}
      pointObj.circle = L.circle(obj.circle.latLng, oriOptions).addTo(this.map) //.marker添加标注点
      if (obj.circle.bindPopup) {
        pointObj.circle.bindPopup(obj.circle.bindPopup.content || '')
      }
      if (obj.circle.openPopup) {
        pointObj.circle.openPopup()
      }
    }
    return pointObj
  }
  /**
   * 添加动画点
   * @param {object} obj latLng 经纬度 color动画点的色值，scale大小
   * @return {newClass} 返回点的地图对象
   * @requires animationPoint.css
   */
  DL.prototype.addAnimationPoint = function (obj) {
    var scale = obj.scale ? obj.scale : 1
    var myIcon = L.divIcon({
      html: '<div class="leaflet-animation-point" style="color:' + obj.color + ';transform: scale(' + scale + ')"><p></p></div>'
    })
    var animationMarker = L.marker(obj.latLng, {
      icon: myIcon
    }).addTo(this.map)

    return animationMarker
  }
  /**
   * 添加聚合点
   * @param {Array} addressPoints 聚合点数据
   * @return {newClass} 返回聚合点对象
   * @requires 依赖插件leaflet.markercluster
   */
  DL.prototype.addMarkerClusterGroup = function (addressPoints, icon) {
    var markers = L.markerClusterGroup()
    for (var i = 0; i < addressPoints.length; i++) {
      var a = addressPoints[i]
      var title = a[2]
      var marker = L.marker(new L.LatLng(a[0], a[1]), {
        // icon: icon,
        title: title
      })
      marker.bindPopup(title)
      markers.addLayer(marker)
    }

    this.map.addLayer(markers)
    return markers
  }
  /**
   * 添加图片图层
   * @param {Array} imageBounds box边界经纬度
   * @param {string} path 图片路径
   * @param {object} oriOptions 原始配置项
   * @returns {newClass} 图片地图对象
   */
  DL.prototype.addImageLayer = function (imageBounds, path, oriOptions) {
    var oriOptions = oriOptions || {}
    var layerImage = L.imageOverlay(path, imageBounds, oriOptions).addTo(this.map)
    return layerImage;
  }
  /**
   * 添加arcgis图层
   * @param url
   * @param {string} type 默认：1.dynamicMapLayer 2.featureLayer
   * @param {object} oriOption 原始配置项
   * @returns {newClass} arcgis地图对象
   * @requires 依赖esri-leaflet.js
   */
  DL.prototype.addArcGisLayer = function (url, type, oriOption) {
    var type = type || 'dynamicMapLayer'
    var options = {
      url,
    }
    if (oriOption && typeof oriOption == 'object') {
      for (var key in oriOption) {
        options[key] = oriOption[key]
      }
    }
    var arcGisLayer = L.esri[type](options)
    this.map.addLayer(arcGisLayer)
    return arcGisLayer
  }

  /**
   * 添加wmts图层
   * @param {string} url 路径
   * @param {object} oriOptions TileLayer.WMTS配置项
   * @returns {newClass}
   * @requires 依赖leaflet-tilelayer-wmts
   */
  DL.prototype.addWMTS = function (url, oriOptions) {
    var options = oriOptions || {}
    var ign = new L.TileLayer.WMTS(url, options)
    this.map.addLayer(ign)
    return ign
  }

  /**
   * 添加kml图层
   * @param {string} kmltext kml数据
   * @returns {newClass} kml地图对象
   * @requires 依赖L.KML
   */
  DL.prototype.addKML = function (kmltext) {
    const parser = new DOMParser()
    const kml = parser.parseFromString(kmltext, 'text/xml')
    const track = new L.KML(kml)
    this.map.addLayer(track)
    const bounds = track.getBounds()
    this.map.fitBounds(bounds)
    return track
  }

  /**
   * 绘制geoJson文件图层
   * @param {*} data json数据
   * @param {object} options：L.geoJSON配置项
   * @returns {newClass} geoJson地图对象
   */
  DL.prototype.addGeoJSON = function (data, options) {
    var options = options || {}
    var geoJson = L.geoJSON(data, options).addTo(this.map)
    return geoJson;
  }

  /**
   * 添加格点
   * @param {Array} gridData 格点数据
   * @param {object} opt 格点配置 className:格点样式名； markName: 格点名称
   */
  DL.prototype.addGdPoint = function (gridData, opt){
    var options = {
      className: '',
      markName: 'warnGdPoints',
      minLatLon: [20, 90.5],
      maxLatLon: [40, 120]
    }
    if(opt && typeof opt == 'object'){
      for (var key in opt) {
        options[key] = opt[key]
      }
    }
    //添加格点方法
    var _this = this;
    function addGdPoint() {
      removeGdPoint();
      var data = gridData;
      var markerIcon;
      var zoom = _this.map.getZoom();
      var _s = getVByZoom(zoom);
      var gj_lng = _s.lon;
      var gj_lat = _s.lat;
      var _temp_lat = [];
      var _indexLng = -1;
      var _indexLat = 0;
      var bd = L.latLngBounds(L.latLng(options.minLatLon[0], options.minLatLon[1]), L.latLng(options.maxLatLon[0],options.maxLatLon[1]));
      var ks_bd = _this.map.getBounds();
      for (var p in data) {
        if (_temp_lat.indexOf(data[p].lat) == -1) {
          _temp_lat.push(data[p].lat);
          _indexLat = 0;
          _indexLng++;
        } else {
          if (_indexLng % gj_lng == 0 && _indexLat % gj_lat == 0) {
            var ll = L.latLng(data[p].lat, data[p].lon);
            var label = L.divIcon({
              html: "<div>" + data[p].val + "</div>",
              className: options.className,
              shadowUrl: '', //阴影地址
              iconSize: [0, 0], //
              shadowSize: [0, 0], // 阴影宽高
              iconAnchor: [0, 0], // 图标锚点
              shadowAnchor: [0, 0], // 阴影锚点
              popupAnchor: [0, 0] // 弹出框弹出位置，相对于图标锚点
            });
            markerIcon = L.marker([data[p].lat, data[p].lon], {
              icon: label,
              zIndex: '9999',
            });
            markerIcon.dataoption = data[p];
            markerIcon.datablname = options.markName;
            if (bd.contains(ll)) {
              if (ks_bd.contains(ll)) {
                _this.map.addLayer(markerIcon);
              }
            }
          }
          _indexLat++;
        }
      }
    }
    addGdPoint();
    //移去格点
    function removeGdPoint() {
      _this.map.eachLayer(function(layer) {
        if (isUndefined(layer.datablname) == options.markName) {
          layer.remove();
        }
      });
    }
    //根据缩放级别稀释数据
    function getVByZoom(zoom) {
      var _s = {};
      if (zoom > 11) {
        _s.lon = 1;
        _s.lat = 2;
      } else if (zoom > 10 && zoom <= 11) {
        _s.lon = 1;
        _s.lat = 2;
      } else if (zoom > 9 && zoom <= 10) {
        _s.lon = 2;
        _s.lat = 3;
      } else if (zoom > 8 && zoom <= 9) {
        _s.lon = 4;
        _s.lat = 5;
      } else if (zoom > 7 && zoom <= 8) {
        _s.lon = 8;
        _s.lat = 10;
      } else if (zoom > 6 && zoom <= 7) {
        _s.lon = 10;
        _s.lat = 12;
      } else if (zoom <= 6) {
        _s.lon = 18;
        _s.lat = 25;
      }
      return _s;
    }
    //判断是否定义
    function isUndefined(str) {
      return typeof str == 'undefined' ? '' : str;
    }
    //监听地图缩放
    this.map.addEventListener("zoomend", addGdPoint);
  }
  /**
   * 添加色斑图
   * @param {object} opt 配置项 features，krigingBounds，krigingColors，bounds，opacity
   * @return {newClass} 色斑图图片地图对象
   * @requires 依赖kriging.js
   */
  DL.prototype.addColorFigure = function (opt) {
    var image = loadkriging(opt.features, opt.krigingBounds, opt.krigingColors)
    var imageBounds = opt.bounds //图片的经纬度范围，西南角点,东北角点(纬度、经度)
    var imageLayer = L.imageOverlay(image, imageBounds, {
      opacity: opt.opacity,
      zIndex: 10
    }) //opacity是透明度
    this.map.addLayer(imageLayer);
    return imageLayer;
  }

  /**
   * 添加风场
   * @param {*} data 风场数据
   * @param {object} oriOption L.velocityLayer原始配置项
   * @returns {newClass} 返回风场图层对象
   */
  DL.prototype.addWindLayer = function (data, oriOption) {
    var options = {
      data: data || [],
      displayValues: true,
      displayOptions: {
        velocityType: 'GBR Wind',
        displayPosition: 'bottomleft',
        displayEmptyString: 'No wind data'
      },
      minVelocity: 0, //Velocity：速率
      maxVelocity: 10,
      velocityScale: 0.005,
      particleMultiplier: 1 / 300, //粒子的数量
      lineWidth: 2, //粒子的粗细
      frameRate: 15, //定义每秒执行的次数
      colorScale: ['rgb(255,255,255)', 'rgb(255,255,255)', 'rgb(255,255,255)', 'rgb(255,255,255)', 'rgb(255,255,255)']
    }
    if (oriOption && typeof oriOption == 'object') {
      for (var key in oriOption) {
        options[key] = oriOption[key]
      }
    }
    var velocityLayer = L.velocityLayer(options)
    this.map.addLayer(velocityLayer)
    return velocityLayer
  }

  /**
   * 定位地图
   * @param {Array} latLng 经纬度
   * @param {number} size  缩放级别
   */
  DL.prototype.setView = function (latLng, size) {
    var defaultSize = this.map.getZoom()
    this.map.setView(latLng, size ? size : defaultSize)
  }

  /**
   * 判断某一经纬度点是否在绘制区域
   * @param {number|string} lon 经度
   * @param {number|string} lat 纬度
   * @param {Array} points 绘制点经纬度集合
   * @returns {boolean} 布尔值
   */
  DL.prototype.isInRegion = function (lon, lat, points) {
    let iSum = 0, iCount = points.length
    let lonStart, lonEnd, latStart, latEnd, dLon
    if (points.length < 3) return false
    for (let i = 0; i < iCount; i++) {
      let next = i + 1
      if (i == iCount - 1) {
        next = 0
      }
      lonStart = points[i][1]
      latStart = points[i][0]
      lonEnd = points[next][1]
      latEnd = points[next][0]

      if ((lat >= latStart && lat < latEnd) || (lat >= latEnd && lat < latStart)) {
        if (Math.abs(latStart - latEnd) > 0) {
          dLon = lonStart - ((lonStart - lonEnd) * (latStart - lat)) / (latStart - latEnd)
          if (dLon < lon) {
            iSum++
          }
        }
      }

    }
    if (iSum % 2 != 0) return true
    return false
  }
  /**
   * 添加线
   * @param {object} options L.polyline原始配置项
   * @return {newClass} polyline的地图对象
   */
  DL.prototype.addPolyline = function (options) {
    var options = options || {};
    var polyline = L.polyline(latlngs, options).addTo(this.map);
    return polyline;
  }
  /**
   * 绘制线双击结束
   * @param options color:折点色值，linecolor: 折线色值
   * @return {Object} polylines: [polyline, polyline], circles: []
   */
  DL.prototype.drawLine = function (options) {
    var opt = {
      color: '#ff0000',
      lineColor: '#ff0000',
    }
    if (options && typeof options == 'object') {
      for (var key in options) {
        opt[key] = options[key]
      }
    }
    var circles = [], polylines = [];
    var points = []
    var lines = new L.polyline(points, {
      color: opt.lineColor,
    })
    var tempLines = new L.polyline([], {
      color: opt.lineColor,
    })
    var ls = [];
    this.map.on('click', onClick); //点击地图
    this.map.on('dblclick', onDoubleClick);
    var _this = this;
    function onClick(e) {
      _this.map.doubleClickZoom.disable();
      points.push([e.latlng.lat, e.latlng.lng])
      lines.addLatLng(e.latlng)
      _this.map.addLayer(lines)
      var circle = L.circle(e.latlng, {
        color: opt.color,
      })
      circles.push(circle);
      _this.map.addLayer(circle)
      _this.map.on('mousemove', onMove) //双击地图
    }

    function onMove(e) {
      if(points.length > 0) {
        ls = [points[points.length - 1],
          [e.latlng.lat, e.latlng.lng]
        ]
        tempLines.setLatLngs(ls)
        _this.map.addLayer(tempLines)
      }
    }

    function onDoubleClick(e) {
      points = [];
      _this.map.doubleClickZoom.enable();
      // lines = new L.polyline(points)
      _this.map.off('mousemove');
      _this.map.off('click');
      _this.map.off('dblclick');
    }

    return {
      circles,
      polylines: [lines, tempLines]
    }
  }
  /**
   * 动态面积测量
   * @returns {Object} init() 开始绘制， remove() 移除绘制
   * @requires 依赖measure,Editable插件包
   */
  DL.prototype.areaMeasure = function () {
    var _this = this;
    var areaMeasure = {
      points: [],
      color: 'red',
      layers: L.layerGroup(),
      polygon: null,
      init: function () {
        areaMeasure.points = []
        areaMeasure.polygon = null;
        _this.map.on('click', areaMeasure.click).on('dblclick', areaMeasure.dblclick)
      },
      close: function () {
        var lab = rectangleMeasure.tips.getLabel()
        var tt = document.createTextNode(rectangleMeasure.tips.getLabel()._content)
        lab._container.innerHTML = ''
        lab._container.appendChild(tt)
        var span = document.createElement('span')
        span.innerHTML = '【关闭】'
        span.style.color = '#00ff40'
        lab._container.appendChild(span)
        L.DomEvent.addListener(span, 'click', function () {
          rectangleMeasure.destory()
        })
      },
      click: function (e) {
        _this.map.doubleClickZoom.disable()
        // 添加点信息
        areaMeasure.points.push(e.latlng)
        // 添加面
        _this.map.on('mousemove', areaMeasure.mousemove)
      },
      mousemove: function (e) {
        areaMeasure.points.push(e.latlng)
        if (areaMeasure.polygon) {
          _this.map.removeLayer(areaMeasure.polygon)
        }
        areaMeasure.polygon = L.polygon(areaMeasure.points, {
          showMeasurements: true,
          color: 'red'
        })
        //areaMeasure.polygon.addTo(map);
        areaMeasure.polygon.addTo(areaMeasure.layers)
        areaMeasure.layers.addTo(_this.map)
        areaMeasure.points.pop()
      },
      dblclick: function (e) { // 双击结束
        areaMeasure.polygon.addTo(areaMeasure.layers)
        areaMeasure.polygon.enableEdit()
        _this.map.on('editable:vertex:drag editable:vertex:deleted', areaMeasure.polygon.updateMeasurements, areaMeasure.polygon)
        _this.map.off('click', areaMeasure.click).off('mousemove', areaMeasure.mousemove).off('dblclick', areaMeasure.dblclick)
      },
      remove: function () {
        areaMeasure.layers.clearLayers();
      }
    }
    // areaMeasure.init();
    // return areaMeasure;
    var initObj = function () {
      return {
        init: areaMeasure.init,
        remove: areaMeasure.remove
      }
    }
    return initObj();
  }
  /**
   * 自定义区域截图
   * @param options font: 字体样式； title: 标题；fillStyle： 字体颜色
   * @param callback 回调函数，参数为绘制外出的url
   */
  DL.prototype.cutOutImage = function (options, callback) {
    var latlngs = []
    var tmprect
    var _this = this
    this.map.on('mousedown', onClick) //点击地图
    this.map.on('mouseup', onDoubleClick)

    function onClick (e) {
      //左上角坐标
      latlngs[0] = [e.latlng.lat, e.latlng.lng]
      //开始绘制，监听鼠标移动事件
      _this.map.on('mousemove', onMove)
    }

    function onMove (e) {
      //取消地图的拖拽方式
      _this.map.dragging.disable()
      latlngs[1] = [e.latlng.lat, e.latlng.lng]
      if (tmprect) {
        tmprect.remove()
      }
      //添加临时矩形
      tmprect = L.rectangle(latlngs, {
        dashArray: 5
      }).addTo(_this.map)
    }

    function onDoubleClick (e) {
      //矩形绘制完成，移除临时矩形，并停止监听鼠标移动事件
      if (tmprect) {
        tmprect.remove()
      }
      _this.map.off('mousemove')
      _this.map.off('mousedown') //点击地图
      _this.map.off('mouseup')
      _this.map.dragging.enable()
      //右下角坐标
      latlngs[1] = [e.latlng.lat, e.latlng.lng]
      _ct(latlngs, _this.id, _this.map, options, callback)
    }
  }

//克瑞金插值法绘制图片
  function loadkriging (tempture, bounds, colors) {
    var canvas = document.createElement('canvas')
    canvas.width = 2000
    canvas.height = 2000
    var t = []
    var x = []
    var y = []
    for (var i = 0, len = tempture.length; i < len; i++) {
      t.push(tempture[i].properties.Temperatur) // 权重值
      x.push(tempture[i].geometry.coordinates[0]) // x
      y.push(tempture[i].geometry.coordinates[1]) // y
    }
    var variogram = kriging.train(t, x, y, 'exponential', 0, 100)
    var grid = kriging.grid(bounds, variogram, 0.05)
    kriging.plot(canvas, grid, [73.4766, 135.088], [18.1055, 53.5693], colors)
    var image = canvas.toDataURL('image/png')
    return image
  }

//绘制图片
  function _ct (latlngs, id, map, opt, callback) {
    var options = {
      font: '18px bold 黑体',
      fillStyle: '#fff',
      title: '',
    }
    if (opt && typeof opt == 'object') {
      for (var key in opt) {
        options[key] = opt[key]
      }
    }
    html2canvas(document.querySelector('#' + id), {
      useCORS: true
    }).then(canvas => {

      var imgEx = []

      if (latlngs[0][0] > latlngs[1][0]) {
        imgEx.push(latlngs[1][0])
        imgEx.push(latlngs[0][0])
      } else {
        imgEx.push(latlngs[0][0])
        imgEx.push(latlngs[1][0])
      }
      if (latlngs[0][1] > latlngs[1][1]) {
        imgEx.push(latlngs[1][1])
        imgEx.push(latlngs[0][1])

      } else {
        imgEx.push(latlngs[0][1])
        imgEx.push(latlngs[1][1])

      }
      var mapEx = map.getBounds()
      //计算要截取范围的屏幕高度
      var height = canvas.height / (mapEx._northEast.lat - mapEx._southWest.lat) * (imgEx[1] - imgEx[0])
      //计算要截取范围的屏幕宽度
      var width = canvas.width / (mapEx._northEast.lng - mapEx._southWest.lng) * (imgEx[3] - imgEx[2])

      //计算要截取图片的起来距离0点的距离
      var startX = canvas.width / (mapEx._northEast.lng - mapEx._southWest.lng) * (imgEx[2] - mapEx._southWest.lng)
      var startY = canvas.height / (mapEx._northEast.lat - mapEx._southWest.lat) * (mapEx._northEast.lat - imgEx[1])
      var canvas1 = document.createElement('canvas')
      var ctx = canvas1.getContext('2d')
      let image = new Image()
      image.setAttribute('crossOrigin', 'anonymous')
      image.src = canvas.toDataURL()
      image.onload = function () {
        canvas1.height = height
        canvas1.width = width
        ctx.drawImage(image, startX, startY, width, height, 0, 0, width, height)

        ///配置标题开始
        // 设置字体
        ctx.font = options.font
        // 设置颜色
        ctx.fillStyle = options.fillStyle
        // 绘制文字（参数：要写的字，x坐标，y坐标）
        var title = options.title
        ctx.fillText(title, 20, 40)
        //配置标题结束
        var url = canvas1.toDataURL()
        callback && callback(url)
      }
    })

  }
  return DL;
}))
